home *** CD-ROM | disk | FTP | other *** search
/ Network PC / Network PC.iso / amiga utilities / communication / internet / amitcp3.0b / src.lha / src / amitcp / api / res_comp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-09-08  |  8.8 KB  |  363 lines

  1. RCS_ID_C="$Id: res_comp.c,v 1.4 1994/01/20 02:16:05 jraja Exp $";
  2. /*
  3.  * Copyright (c) 1993 AmiTCP/IP Group, <amitcp-group@hut.fi>
  4.  *                    Helsinki University of Technology, Finland.
  5.  *                    All rights reserved.
  6.  *
  7.  * Last modified: Thu Jan 20 02:13:54 1994 jraja
  8.  *
  9.  * HISTORY
  10.  * $Log: res_comp.c,v $
  11.  * Revision 1.4  1994/01/20  02:16:05  jraja
  12.  * Added #include <conf.h> as the first include.
  13.  *
  14.  * Revision 1.3  1993/06/04  11:16:15  jraja
  15.  * Fixes for first public release.
  16.  *
  17.  * Revision 1.2  1993/06/02  19:26:17  too
  18.  * Moved resolver stuff here from kern/ -directory
  19.  *
  20.  * Revision 1.1  1993/06/01  16:30:33  too
  21.  * Initial revision
  22.  *
  23.  * Revision 1.1  93/04/25  12:46:13  12:46:13  too (Tomi Ollila)
  24.  * Initial revision
  25.  * 
  26.  *
  27.  */
  28. /*
  29.  * Copyright (c) 1985 Regents of the University of California.
  30.  * All rights reserved.
  31.  *
  32.  * Redistribution and use in source and binary forms, with or without
  33.  * modification, are permitted provided that the following conditions
  34.  * are met:
  35.  * 1. Redistributions of source code must retain the above copyright
  36.  *    notice, this list of conditions and the following disclaimer.
  37.  * 2. Redistributions in binary form must reproduce the above copyright
  38.  *    notice, this list of conditions and the following disclaimer in the
  39.  *    documentation and/or other materials provided with the distribution.
  40.  * 3. All advertising materials mentioning features or use of this software
  41.  *    must display the following acknowledgement:
  42.  *    This product includes software developed by the University of
  43.  *    California, Berkeley and its contributors.
  44.  * 4. Neither the name of the University nor the names of its contributors
  45.  *    may be used to endorse or promote products derived from this software
  46.  *    without specific prior written permission.
  47.  *
  48.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  49.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  50.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  51.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  52.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  53.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  54.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  55.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  56.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  57.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  58.  * SUCH DAMAGE.
  59.  */
  60.  
  61. #if defined(LIBC_SCCS) && !defined(lint)
  62. static char sccsid[] = "@(#)res_comp.c    6.22 (Berkeley) 3/19/91";
  63. #endif /* LIBC_SCCS and not lint */
  64.  
  65. #include <conf.h>
  66.  
  67. #include <sys/param.h>
  68. #include <api/arpa_nameser.h>
  69. #include <netinet/in.h>
  70.      
  71. #include <exec/semaphores.h>     
  72.      
  73. #include <kern/amiga_netdb.h>     
  74. #include <api/resolv.h>
  75.  
  76. static int dn_find(u_char *exp_dn, u_char *msg,
  77.            u_char **dnptrs, u_char **lastdnptr);
  78.  
  79. /*
  80.  * Expand compressed domain name 'comp_dn' to full domain name.
  81.  * 'msg' is a pointer to the begining of the message,
  82.  * 'eomorig' points to the first location after the message,
  83.  * 'exp_dn' is a pointer to a buffer of size 'length' for the result.
  84.  * Return size of compressed name or -1 if there was an error.
  85.  */
  86. int
  87. dn_expand(const u_char *msg, const u_char *eomorig, const u_char *comp_dn,
  88.       u_char *exp_dn, int length)
  89. {
  90.     register u_char *cp, *dn;
  91.     register int n, c;
  92.     u_char *eom;
  93.     int len = -1, checked = 0;
  94.  
  95.     dn = exp_dn;
  96.     cp = (u_char *)comp_dn;
  97.     eom = exp_dn + length;
  98.     /*
  99.      * fetch next label in domain name
  100.      */
  101.     while (n = *cp++) {
  102.         /*
  103.          * Check for indirection
  104.          */
  105.         switch (n & INDIR_MASK) {
  106.         case 0:
  107.             if (dn != exp_dn) {
  108.                 if (dn >= eom)
  109.                     return (-1);
  110.                 *dn++ = '.';
  111.             }
  112.             if (dn+n >= eom)
  113.                 return (-1);
  114.             checked += n + 1;
  115.             while (--n >= 0) {
  116.                 if ((c = *cp++) == '.') {
  117.                     if (dn + n + 2 >= eom)
  118.                         return (-1);
  119.                     *dn++ = '\\';
  120.                 }
  121.                 *dn++ = c;
  122.                 if (cp >= eomorig)    /* out of range */
  123.                     return(-1);
  124.             }
  125.             break;
  126.  
  127.         case INDIR_MASK:
  128.             if (len < 0)
  129.                 len = cp - comp_dn + 1;
  130.             cp = (u_char *)msg + (((n & 0x3f) << 8) | (*cp & 0xff));
  131.             if (cp < msg || cp >= eomorig)    /* out of range */
  132.                 return(-1);
  133.             checked += 2;
  134.             /*
  135.              * Check for loops in the compressed name;
  136.              * if we've looked at the whole message,
  137.              * there must be a loop.
  138.              */
  139.             if (checked >= eomorig - msg)
  140.                 return (-1);
  141.             break;
  142.  
  143.         default:
  144.             return (-1);            /* flag error */
  145.         }
  146.     }
  147.     *dn = '\0';
  148.     if (len < 0)
  149.         len = cp - comp_dn;
  150.     return (len);
  151. }
  152.  
  153. /*
  154.  * Compress domain name 'exp_dn' into 'comp_dn'.
  155.  * Return the size of the compressed name or -1.
  156.  * 'length' is the size of the array pointed to by 'comp_dn'.
  157.  * 'dnptrs' is a list of pointers to previous compressed names. dnptrs[0]
  158.  * is a pointer to the beginning of the message. The list ends with NULL.
  159.  * 'lastdnptr' is a pointer to the end of the arrary pointed to
  160.  * by 'dnptrs'. Side effect is to update the list of pointers for
  161.  * labels inserted into the message as we compress the name.
  162.  * If 'dnptr' is NULL, we don't try to compress names. If 'lastdnptr'
  163.  * is NULL, we don't update the list.
  164.  */
  165. int
  166. dn_comp(const u_char *exp_dn, u_char *comp_dn, int length,
  167.     u_char **dnptrs, u_char **lastdnptr)
  168. {
  169.     register u_char *cp, *dn;
  170.     register int c, l;
  171.     u_char **cpp, **lpp, *sp, *eob;
  172.     u_char *msg;
  173.  
  174.     dn = (u_char *)exp_dn;
  175.     cp = comp_dn;
  176.     eob = cp + length;
  177.     if (dnptrs != NULL) {
  178.         if ((msg = *dnptrs++) != NULL) {
  179.             for (cpp = dnptrs; *cpp != NULL; cpp++)
  180.                 ;
  181.             lpp = cpp;    /* end of list to search */
  182.         }
  183.     } else
  184.         msg = NULL;
  185.     for (c = *dn++; c != '\0'; ) {
  186.         /* look to see if we can use pointers */
  187.         if (msg != NULL) {
  188.             if ((l = dn_find(dn-1, msg, dnptrs, lpp)) >= 0) {
  189.                 if (cp+1 >= eob)
  190.                     return (-1);
  191.                 *cp++ = (l >> 8) | INDIR_MASK;
  192.                 *cp++ = l % 256;
  193.                 return (cp - comp_dn);
  194.             }
  195.             /* not found, save it */
  196.             if (lastdnptr != NULL && cpp < lastdnptr-1) {
  197.                 *cpp++ = cp;
  198.                 *cpp = NULL;
  199.             }
  200.         }
  201.         sp = cp++;    /* save ptr to length byte */
  202.         do {
  203.             if (c == '.') {
  204.                 c = *dn++;
  205.                 break;
  206.             }
  207.             if (c == '\\') {
  208.                 if ((c = *dn++) == '\0')
  209.                     break;
  210.             }
  211.             if (cp >= eob) {
  212.                 if (msg != NULL)
  213.                     *lpp = NULL;
  214.                 return (-1);
  215.             }
  216.             *cp++ = c;
  217.         } while ((c = *dn++) != '\0');
  218.         /* catch trailing '.'s but not '..' */
  219.         if ((l = cp - sp - 1) == 0 && c == '\0') {
  220.             cp--;
  221.             break;
  222.         }
  223.         if (l <= 0 || l > MAXLABEL) {
  224.             if (msg != NULL)
  225.                 *lpp = NULL;
  226.             return (-1);
  227.         }
  228.         *sp = l;
  229.     }
  230.     if (cp >= eob) {
  231.         if (msg != NULL)
  232.             *lpp = NULL;
  233.         return (-1);
  234.     }
  235.     *cp++ = '\0';
  236.     return (cp - comp_dn);
  237. }
  238.  
  239. /*
  240.  * Skip over a compressed domain name. Return the size or -1.
  241.  */
  242. int
  243. __dn_skipname(const u_char *comp_dn, const u_char *eom)
  244. {
  245.     register u_char *cp;
  246.     register int n;
  247.  
  248.     cp = (u_char *)comp_dn;
  249.     while (cp < eom && (n = *cp++)) {
  250.         /*
  251.          * check for indirection
  252.          */
  253.         switch (n & INDIR_MASK) {
  254.         case 0:        /* normal case, n == len */
  255.             cp += n;
  256.             continue;
  257.         default:    /* illegal type */
  258.             return (-1);
  259.         case INDIR_MASK:    /* indirection */
  260.             cp++;
  261.         }
  262.         break;
  263.     }
  264.     return (cp - comp_dn);
  265. }
  266.  
  267. /*
  268.  * Search for expanded name from a list of previously compressed names.
  269.  * Return the offset from msg if found or -1.
  270.  * dnptrs is the pointer to the first name on the list,
  271.  * not the pointer to the start of the message.
  272.  */
  273. static int
  274. dn_find(u_char *exp_dn, u_char *msg,
  275.     u_char **dnptrs, u_char **lastdnptr)
  276. {
  277.     register u_char *dn, *cp, **cpp;
  278.     register int n;
  279.     u_char *sp;
  280.  
  281.     for (cpp = dnptrs; cpp < lastdnptr; cpp++) {
  282.         dn = exp_dn;
  283.         sp = cp = *cpp;
  284.         while (n = *cp++) {
  285.             /*
  286.              * check for indirection
  287.              */
  288.             switch (n & INDIR_MASK) {
  289.             case 0:        /* normal case, n == len */
  290.                 while (--n >= 0) {
  291.                     if (*dn == '.')
  292.                         goto next;
  293.                     if (*dn == '\\')
  294.                         dn++;
  295.                     if (*dn++ != *cp++)
  296.                         goto next;
  297.                 }
  298.                 if ((n = *dn++) == '\0' && *cp == '\0')
  299.                     return (sp - msg);
  300.                 if (n == '.')
  301.                     continue;
  302.                 goto next;
  303.  
  304.             default:    /* illegal type */
  305.                 return (-1);
  306.  
  307.             case INDIR_MASK:    /* indirection */
  308.                 cp = msg + (((n & 0x3f) << 8) | *cp);
  309.             }
  310.         }
  311.         if (*dn == '\0')
  312.             return (sp - msg);
  313.     next:    ;
  314.     }
  315.     return (-1);
  316. }
  317.  
  318. /*
  319.  * Routines to insert/extract short/long's. Must account for byte
  320.  * order and non-alignment problems. This code at least has the
  321.  * advantage of being portable.
  322.  *
  323.  * used by sendmail.
  324.  */
  325.  
  326. u_short
  327. _getshort(u_char *msgp)
  328. {
  329.     register u_char *p = (u_char *) msgp;
  330.     register u_short u;
  331.  
  332.     u = *p++ << 8;
  333.     return ((u_short)(u | *p));
  334. }
  335.  
  336. u_long
  337. _getlong(u_char *msgp)
  338. {
  339.     register u_char *p = (u_char *) msgp;
  340.     register u_long u;
  341.  
  342.     u = *p++; u <<= 8;
  343.     u |= *p++; u <<= 8;
  344.     u |= *p++; u <<= 8;
  345.     return (u | *p);
  346. }
  347.  
  348. void
  349. __putshort(register u_short s, register u_char *msgp)
  350. {
  351.     msgp[1] = s;
  352.     msgp[0] = s >> 8;
  353. }
  354.  
  355. void
  356. __putlong(register u_long l, register u_char *msgp)
  357. {
  358.     msgp[3] = l;
  359.     msgp[2] = (l >>= 8);
  360.     msgp[1] = (l >>= 8);
  361.     msgp[0] = l >> 8;
  362. }
  363.